/**
 * 
 */
package org.youisoft.summer.evaluator.function.control;

import org.youisoft.summer.evaluator.InvokeException;
import org.youisoft.summer.evaluator.context.CalContext;
import org.youisoft.summer.evaluator.function.AbstractFunction;
import org.youisoft.summer.evaluator.operator.Operator;
import org.youisoft.summer.evaluator.operator.base.ClosureOperator;
import org.youisoft.summer.evaluator.operator.base.NumberOperator;

/**
 * @author zijiang.jl
 *
 */
public class ForFunction extends AbstractFunction{
	
	@Override
	protected boolean checkOperator(int index, Operator<?> operator) {
		if(index==0&&NumberOperator.class.isAssignableFrom(operator.getClass())){
			return true;
		}
		
		if(index==1&&NumberOperator.class.isAssignableFrom(operator.getClass())){
			return true;
		}
		
		if(index==2&&NumberOperator.class.isAssignableFrom(operator.getClass())){
			return true;
		}
		
		if(index==3&&ClosureOperator.class.isAssignableFrom(operator.getClass())){
			return true;
		}
		return false;
	}

	@Override
	public <C, R, P> Operator<?> doInvoke(CalContext<C, R, P> context,
			Operator<?>... operator) throws InvokeException {
		int i=NumberOperator.class.cast(operator[0]).value().intValue();
		int j=NumberOperator.class.cast(operator[1]).value().intValue();
		int k=NumberOperator.class.cast(operator[2]).value().intValue();
		final ClosureOperator call=ClosureOperator.class.cast(operator[3]);
		for(int a=i;a<j;a=a+k){
			try{
				call.execute(context);
				if(context.isNeedBreak()) break;
				if(context.isNeedContinue()) continue;
				if(context.isNeedPause()) Thread.sleep(context.getPauseTime());
			}catch(java.lang.Throwable t){
				logger.error(t.getMessage(), t);
			}


		}
		return Operator.nullInstance;
	}

	@Override
	protected int minOperatorCount() {
		return 4;
	}
	
	
}
